package net.qiqbframework.modelling.repository;


import net.qiqbframework.modelling.domain.Aggregate;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Consumer;

/**
 * 聚合仓库
 *
 * @param <A>
 */
public interface AggregateRepository<A> {
    /**
     * 业务ID加载。此方法
     *
     * @param aggregateBizIdentifier 业务ID
     * @return
     */
    default Aggregate<A> load(@Nonnull AggregateBizIdentifierVoucher aggregateBizIdentifier) {
        return load(aggregateBizIdentifier, null);
    }

    Aggregate<A> load(@Nonnull AggregateBizIdentifierVoucher aggregateIdentifier, Long expectedVersion);

    /**
     * 预批量加载。此方法一般在批量命令中提前加载聚合根对象，此方法仅仅是预备加载。
     *
     * @param bizIdentifierVouchers 待预加载的聚合业务ID
     */
    void prepareBatchLoad(List<AggregateBizIdentifierVoucher> bizIdentifierVouchers);

    /**
     * 批量加载
     *
     * @param bizIdentifierVouchers
     * @return
     */
    Map<AggregateBizIdentifierVoucher, Aggregate<A>> batchLoad(List<AggregateBizIdentifierVoucher> bizIdentifierVouchers);

    /**
     * 从缓冲中加载
     *
     * @param bizIdentifierVoucher
     * @return
     */
    Aggregate<A> loadFromCache(AggregateBizIdentifierVoucher bizIdentifierVoucher);

    Aggregate<A> newInstance(@Nonnull Callable<A> factoryMethod) throws Exception;

    default Aggregate<A> newInstance(Callable<A> factoryMethod, Consumer<Aggregate<A>> initMethod) throws Exception {
        Aggregate<A> aggregate = newInstance(factoryMethod);
        initMethod.accept(aggregate);
        return aggregate;
    }

}
